#define _GNU_SOURCE
#include <sys/socket.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/un.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <signal.h>
#include <execinfo.h> //for backtrace


#include "pb.h"
#include "pb_decode.h"
#include "pb_encode.h"
#include "list.h"
#include "uthash.h"
#include "somb.h"
#include "somb_daemon.h"
#include "somb_daemon_message.h"
#include "somb_daemon.pb.h"
#include "somb_log.h"
#include "somb_conf.h"



ST_SOMB_DAEMON_SERVICE_LIST *NsServieList= NULL;
ST_SOMB_DAEMON_SUB_NS *pstDaemonSubNsHead = NULL;
static uint32_t subns_id = 1;
static int daemon_skfd=0;
static int daemon_ctrl_sk = 0; 

ST_SOMB_DAEMON_CONF gstSombConf = {0};

void somb_daemon_report_servicestatus_to_subns(ST_SOMB_DAEMON_SERVICE_LIST *s,ST_SOMB_DAEMON_SUB_NS *pstSubNs,bool bEnable)
{
    int ret;
    somb_service_available_msg AvaMsg = somb_service_available_msg_init_zero;
    AvaMsg.service_id = s->id;
    AvaMsg.service_type = s->type;
    AvaMsg.available =  bEnable;

    if(bEnable)
    {
        AvaMsg.has_subns = true;
        AvaMsg.subns.sub_ns_id = s->pstNsAddr->id;
        snprintf(AvaMsg.subns.sub_ns_addr,sizeof(AvaMsg.subns.sub_ns_addr),"%s",s->pstNsAddr->addr);
        snprintf(AvaMsg.subns.sub_ns_name,sizeof(AvaMsg.subns.sub_ns_name),"%s",s->pstNsAddr->name);
    }
    else
    {
        AvaMsg.has_subns = false;
    }

    ret =somb_daemon_msg_send_to_sub_ns(0,pstSubNs,somb_daemon_msgid_service_available_2_subns, &AvaMsg, somb_service_available_msg_fields,somb_service_available_msg_size);
    if(SOMB_OK != ret)
    {
        SOMB_LOG_ERR("somb daemon: report to sub ns(%d)  Service(%08X) available(%d) failed",pstSubNs->id,s->id,bEnable);
    }
    else
    {
        SOMB_LOG_DEBUG("somb daemon: report to sub ns(%d)  Service(%08X) available(%d) success",pstSubNs->id,s->id,bEnable);
    }

}
void somb_daemon_remove_subns_by_fd(int fd)
{
    //struct somb_daemon_sub_ns *pstRegSubNs=NULL;
    //int ret;
    bool find_sub_ns = false;
    ST_SOMB_DAEMON_SUB_NS *item = NULL,*tmp=NULL;
    HASH_ITER(hh, pstDaemonSubNsHead, item, tmp) 
    {
        if(item->clientfd == fd)
        {
            find_sub_ns = true;
            break;
        }
    }

    if(!find_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon: remove subns by fd(%d),but no subns find ",fd);
        return;
    }
    else
    {
        item->status = SOMB_DAEMON_NS_STATUS_OFFLINE;
        SOMB_LOG_WARN("somb daemon: remove subns(%s) by fd(%d) success,id(%d)-pid(%d)-addr(%s)-offline",item->name,fd,item->id,item->pid,item->addr);
        //Notify referred Service is offline & Free malloc 
        struct somb_daemon_subns_owned_service *item1=NULL,*tmp1=NULL;
        DL_FOREACH_SAFE(item->owned_servicelist_head,item1,tmp1)
        {
            if(item1->pstService &&
                item1->pstService->listener_sub_ns_list_head)
            {
                item1->pstService->pstNsAddr = NULL;
                item1->pstService->status = SOMB_SERVICE_STATUS_INVALID;

                struct somb_daemon_service_listened_subns *item2,*tmp2;
                DL_FOREACH_SAFE(item1->pstService->listener_sub_ns_list_head,item2,tmp2)
                {
                    somb_service_available_msg AvaMsg = somb_service_available_msg_init_zero;
                    AvaMsg.service_id = item1->pstService->id;
                    AvaMsg.service_type = item1->pstService->type;
                    AvaMsg.available =  false;

                    somb_daemon_msg_send_to_sub_ns(0,item2->listener_info.pstSubNs,\
                            somb_daemon_msgid_service_available_2_subns, \
                            &AvaMsg, somb_service_available_msg_fields,somb_service_available_msg_size);
                }

            }

            DL_DELETE(item->owned_servicelist_head,item1);
            free(item1);
        }

        //we don't remove the subns from hashtable, if the sub ns register again,it will use memory again
        //HASH_DEL(pstDaemonSubNsHead,item);
    }

}
void somb_daemon_add_subns(uint8_t client_name[],uint32_t client_pid,int client_fd)
{
    ST_SOMB_DAEMON_SUB_NS *item = NULL;
    HASH_FIND_STR(pstDaemonSubNsHead,client_name,item);
    if(NULL == item)
    {
        item = (ST_SOMB_DAEMON_SUB_NS*)malloc(sizeof *item);
        if(NULL == item)
        {
            SOMB_LOG_ERR("somb daemon,malloc for sub ns ,sub ns(%s) pid=%d ",client_name,client_pid);
            return ;
        }

        bzero(item,sizeof(ST_SOMB_DAEMON_SUB_NS));

        item->pid = client_pid;
        item->id = subns_id++;
        item->ref = 0;
        item->status = SOMB_DAEMON_NS_STATUS_ONLINE;
        item->owned_servicelist_head=NULL;
        item->clientfd = client_fd;
        snprintf(item->name,sizeof(item->name),"%s",client_name);
        snprintf(item->addr,sizeof(item->addr),SOMB_SUB_NS_ADDR_FMT1,item->id);
        HASH_ADD_STR(pstDaemonSubNsHead, name, item);
        SOMB_LOG_DEBUG("somb daemon, save sub ns(%s) with pid(%d) fd(%d) online",client_name,client_pid,client_fd);
    }
    else
    {
        SOMB_LOG_ERR("somb daemon, duplicate reg sub ns(%s), oldpid(%d) newpid(%d) with fd(%d)",item->name,item->pid,client_pid,client_fd);
        item->pid = client_pid;
        item->clientfd = client_fd;
        item->status = SOMB_DAEMON_NS_STATUS_ONLINE;

        //need to broadcast to all other subns with new addr(actually same), and reconnect to new subns
        //need more think....
    }


}

void somb_daemon_reg_subns(somb_sub_ns_reg_req *msgreq)
{

    ST_SOMB_DAEMON_SUB_NS *item = NULL;
    HASH_FIND_STR(pstDaemonSubNsHead,msgreq->sub_ns_name,item);
    if(NULL == item)
    {
        SOMB_LOG_ERR("somb daemon, reg sub ns(%s) with pid(%d) error",msgreq->sub_ns_name,msgreq->pid);
    }
    else
    {
        SOMB_LOG_INFO("somb daemon:new sub ns(%s),pid(%d) ns_id(%d) register to daemon success",item->name,item->pid,item->id);
    }


    somb_sub_ns_reg_resp msgresp = somb_sub_ns_reg_resp_init_zero;
    msgresp.pid = msgreq->pid;
    msgresp.sub_ns_id = item==NULL?0:item->id;

    somb_daemon_msg_send_to_sub_ns(daemon_skfd,item,
            somb_daemon_msgid_register_sub_ns,
            &msgresp,somb_sub_ns_reg_resp_fields,somb_sub_ns_reg_resp_size);

}



void somb_daemon_reg_service(somb_msg_reg *msgreg)
{
    struct somb_daemon_sub_ns *pstRegSubNs=NULL;
    int ret;
    bool find_sub_ns = false;
    ST_SOMB_DAEMON_SUB_NS *item = NULL,*tmp=NULL;
    HASH_ITER(hh, pstDaemonSubNsHead, item, tmp) 
    {
        if(item->id == msgreg->subns.sub_ns_id)
        {
            find_sub_ns = true;
            break;
        }
    }

    if(!find_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon: sub ns id(%d) addr(%s) reg service failed,but no sub ns reg before",msgreg->subns.sub_ns_id,msgreg->subns.sub_ns_addr);
        return;
    }
    
    pstRegSubNs = item;

    uint32_t loop = 0;
    for(;loop < msgreg->service_item_count;loop++)
    {
        ST_SOMB_DAEMON_SERVICE_LIST *s = NULL;
        HASH_FIND_INT(NsServieList,&(msgreg->service_item[loop].service_id),s);
        if(NULL == s)
        {
            s = (ST_SOMB_DAEMON_SERVICE_LIST*)malloc(sizeof *s);
            if(NULL == s)
            {
                SOMB_LOG_ERR("somb daemon: sub ns id(%d) addr(%s) reg service(%08x) malloc failed",msgreg->subns.sub_ns_id,msgreg->subns.sub_ns_addr,
                        msgreg->service_item[loop].service_id);
                return ;
            }
            bzero(s,sizeof(*s));

            s->id = msgreg->service_item[loop].service_id;
            s->type = msgreg->service_item[loop].service_type;
            s->status = SOMB_SERVICE_STATUS_READY;
            s->pstNsAddr = pstRegSubNs;
            s->listener_sub_ns_list_head = NULL;
            HASH_ADD_INT(NsServieList, id, s);

            SOMB_LOG_INFO("somb daemon: sub ns id(%d) addr(%s) reg new serviceid(%08x) type=%d",msgreg->subns.sub_ns_id,msgreg->subns.sub_ns_addr,s->id,s->type);
            struct somb_daemon_subns_owned_service *owned_s = (struct somb_daemon_subns_owned_service*)malloc(sizeof *owned_s);
            if(NULL == owned_s)
            {
                SOMB_LOG_ERR("somb daemon: sub ns id(%d) addr(%s) reg service(%08x) malloc for owned s failed",msgreg->subns.sub_ns_id,msgreg->subns.sub_ns_addr, msgreg->service_item[loop].service_id);
                return ;
            }

            bzero(owned_s,sizeof(*owned_s));
            owned_s->pstService= s;
            DL_PREPEND(pstRegSubNs->owned_servicelist_head,owned_s);
            pstRegSubNs->ref ++; 

        }
        else // registered already
        {
            s->id = msgreg->service_item[loop].service_id;
            s->type = msgreg->service_item[loop].service_type;
            s->status = SOMB_SERVICE_STATUS_READY;
            s->pstNsAddr = pstRegSubNs;

            struct somb_daemon_subns_owned_service *owned_s = (struct somb_daemon_subns_owned_service*)malloc(sizeof *owned_s);
            if(NULL == owned_s)
            {
                SOMB_LOG_ERR("somb daemon: sub ns id(%d) addr(%s) reg service(%08x) malloc for owned s failed",msgreg->subns.sub_ns_id,msgreg->subns.sub_ns_addr, msgreg->service_item[loop].service_id);
                return ;
            }

            bzero(owned_s,sizeof(*owned_s));
            owned_s->pstService= s;
            DL_PREPEND(pstRegSubNs->owned_servicelist_head,owned_s);
            //pstRegSubNs->ref ++; 

            uint32_t empty= 0;
            DL_EMPTY(s->listener_sub_ns_list_head,empty);
            SOMB_LOG_INFO("somb daemon: sub ns id(%d) addr(%s) reg modify serviceid(%08x),listen_subns=%d",msgreg->subns.sub_ns_id,msgreg->subns.sub_ns_addr,msgreg->service_item[loop].service_id,empty);
            if(empty == 0)//0 means not empty
            {
                somb_event_listener_reg_2_subns msgreq = somb_event_listener_reg_2_subns_init_zero;
                msgreq.service_id = s->id;
                msgreq.subns_count = 0;
                msgreq.flags_count = 0;
                msgreq.reg = true;
                uint32_t loop=0;
                struct somb_daemon_service_listened_subns *item1=NULL,*tmp1=NULL;
                DL_FOREACH_SAFE(s->listener_sub_ns_list_head,item1,tmp1)
                {
                    //item1->pstSubNs
                    msgreq.subns_count++;
                    msgreq.subns[loop].sub_ns_id = item1->listener_info.pstSubNs->id;

                    msgreq.flags_count++;
                    msgreq.flags[loop]= item1->listener_info.listener_flags;
                    snprintf(msgreq.subns[loop].sub_ns_name,sizeof(msgreq.subns[loop].sub_ns_name),"%s",item1->listener_info.pstSubNs->name);
                    snprintf(msgreq.subns[loop].sub_ns_addr,sizeof(msgreq.subns[loop].sub_ns_addr),"%s",item1->listener_info.pstSubNs->addr);
                    loop++;

                    if(s->type == SOMB_SVC_TYPE_METHOD)
                    {
                        //notify the register,the service is available now
                        somb_service_available_msg AvaMsg = somb_service_available_msg_init_zero;
                        AvaMsg.service_id = s->id;
                        AvaMsg.service_type = s->type;
                        AvaMsg.available =  true;

                        AvaMsg.has_subns = true;
                        AvaMsg.subns.sub_ns_id = pstRegSubNs->id;
                        snprintf(AvaMsg.subns.sub_ns_addr,sizeof(AvaMsg.subns.sub_ns_addr),"%s",pstRegSubNs->addr);
                        snprintf(AvaMsg.subns.sub_ns_name,sizeof(AvaMsg.subns.sub_ns_name),"%s",pstRegSubNs->name);
                        ret =somb_daemon_msg_send_to_sub_ns(daemon_skfd,item1->listener_info.pstSubNs,somb_daemon_msgid_service_available_2_subns, &AvaMsg, somb_service_available_msg_fields,somb_service_available_msg_size);
                        if(SOMB_OK != ret)
                        {
                            SOMB_LOG_ERR("somb daemon: report to sub ns(%d)  Service(%08X) available failed ",msgreg->subns.sub_ns_id,s->id);
                        }
                    }

                }

                SOMB_LOG_INFO("somb daemon:(%s) sub ns(%d) addr(%s) reg service ,get %d listen sub ns",
                        pstRegSubNs->name,pstRegSubNs->id,pstRegSubNs->addr,msgreq.subns_count);

                somb_daemon_msg_send_to_sub_ns(daemon_skfd,pstRegSubNs,
                    somb_daemon_msgid_listen_event_2_subns,
                    &msgreq,
                    somb_event_listener_reg_2_subns_fields, somb_event_listener_reg_2_subns_size);


            }
        }
    }

    SOMB_LOG_INFO("somb daemon: sub ns(%s) (%d) addr(%s) reg service num(%d) done",pstRegSubNs->name,pstRegSubNs->id,pstRegSubNs->addr,pstRegSubNs->ref);
}

void somb_daemon_unreg_service(somb_msg_unreg *msgunreg)
{

    struct somb_daemon_sub_ns *pstRegSubNs=NULL;
    int ret;
    bool find_sub_ns = false;
    ST_SOMB_DAEMON_SUB_NS *item = NULL,*tmp=NULL;
    HASH_ITER(hh, pstDaemonSubNsHead, item, tmp) 
    {
        if(item->id == msgunreg->sub_ns_id)
        {
            find_sub_ns = true;
            break;
        }
    }

    if(!find_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon: sub ns id(%d) unreg service(%d) failed,but no sub ns reg before",msgunreg->sub_ns_id,msgunreg->service_id_count);
        return;
    }
    
    pstRegSubNs = item;

    uint32_t loop = 0;
    for(;loop < msgunreg->service_id_count;loop++)
    {
        ST_SOMB_DAEMON_SERVICE_LIST *s = NULL;
        HASH_FIND_INT(NsServieList,&(msgunreg->service_id[loop]),s);
        if(NULL != s)
        {
             HASH_DEL(NsServieList, s);
             pstRegSubNs->ref --;
             struct somb_daemon_subns_owned_service *item1=NULL,*tmp=NULL;
             DL_FOREACH_SAFE(pstRegSubNs->owned_servicelist_head,item1,tmp)
             {
                 if(item1->pstService == s)
                 {
                    DL_DELETE(pstRegSubNs->owned_servicelist_head,item1);
                    free(item1);
                    break;
                 }
             }

            uint32_t empty= 0;
            DL_EMPTY(s->listener_sub_ns_list_head,empty);
            if(empty == 0)//0 means not empty
            {
#if 0
                somb_event_listener_reg_2_subns msgreq = somb_event_listener_reg_2_subns_init_zero;
                msgreq.service_id = s->id;
                msgreq.subns_count = 0;
                msgreq.reg = true;
#endif
                //uint32_t loop=0;
                struct somb_daemon_service_listened_subns *item1=NULL,*tmp1=NULL;
                DL_FOREACH_SAFE(s->listener_sub_ns_list_head,item1,tmp1)
                {
                    if(s->type == SOMB_SVC_TYPE_METHOD)
                    {
                        //notify the register,the service is available now
                        somb_service_available_msg AvaMsg = somb_service_available_msg_init_zero;
                        AvaMsg.service_id = s->id;
                        AvaMsg.service_type = s->type;
                        AvaMsg.available =  false;

                        AvaMsg.has_subns = false;
                        ret =somb_daemon_msg_send_to_sub_ns(daemon_skfd,item1->listener_info.pstSubNs,somb_daemon_msgid_service_available_2_subns, &AvaMsg, somb_service_available_msg_fields,somb_service_available_msg_size);
                        if(SOMB_OK != ret)
                        {
                            SOMB_LOG_ERR("somb daemon: report to sub ns(%d)  Service(%08X) unavailable ",item1->listener_info.pstSubNs->id,s->id);
                        }

                    }
                }

            }

            if(pstRegSubNs->ref == 0)
            {
                SOMB_LOG_INFO("somb daemon: sub ns(%d) addr(%s) no service(%08x), delete...",s->pstNsAddr->id,s->pstNsAddr->addr,s->pstNsAddr->ref);
                 HASH_DEL(pstDaemonSubNsHead,pstRegSubNs);
                 free(pstRegSubNs);
                 s->pstNsAddr=NULL;
            }

            free(s);
        }
    }
}

void somb_daemon_get_service(somb_msg_get_service_req *msgsreq)
{
    somb_msg_get_service_resp msgsresp = somb_msg_get_service_resp_init_zero;
    ST_SOMB_DAEMON_SUB_NS *item=NULL,*tmp=NULL; 
    uint32_t msgid = somb_daemon_msgid_get_service;

    bool find_sub_ns = false;
    HASH_ITER(hh, pstDaemonSubNsHead, item, tmp) 
    {
        if(item->id == msgsreq->sub_ns_id)
        {
            find_sub_ns = true;
            break;
        }
    }
    if(!find_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon: get ServiceId(%08x) ok, but find requester's sub ns(%d) pid=%d failed.",msgsreq->service_id,msgsreq->sub_ns_id,msgsreq->pid);
        return ;   
    }

    ST_SOMB_DAEMON_SERVICE_LIST *s = NULL;
    HASH_FIND_INT(NsServieList,&(msgsreq->service_id),s);
    if(NULL != s)
    {
        msgsresp.service_id = msgsreq->service_id;
        msgsresp.service_type = s->type;
        if(s->pstNsAddr)
        {
            msgsresp.has_subns = true;
            msgsresp.subns.sub_ns_id =  s->pstNsAddr->id;
            snprintf(msgsresp.subns.sub_ns_addr,sizeof(msgsresp.subns.sub_ns_addr),"%s",s->pstNsAddr->addr);
            snprintf(msgsresp.subns.sub_ns_name,sizeof(msgsresp.subns.sub_ns_name),"%s",s->pstNsAddr->name);
        }
        else
        {
            msgsresp.has_subns = false;
        }
        SOMB_LOG_DEBUG("somb daemon: SubNs(%d)-pid(%d) get ServiceId(%08x) type(%d) addr=%s",msgsreq->sub_ns_id,msgsreq->pid,msgsreq->service_id,s->type,msgsresp.subns.sub_ns_addr);
    }
    else
    {
        msgsresp.service_id = msgsreq->service_id;
        msgsresp.has_subns = false;
        SOMB_LOG_ERR("somb daemon: SubNs(%d)-pid(%d) get ServiceId(%08x) has_subns=false",msgsreq->sub_ns_id,msgsreq->pid,msgsreq->service_id);
    }
    
    somb_daemon_msg_send_to_sub_ns(daemon_skfd,item,
            msgid, &msgsresp,
            somb_msg_get_service_resp_fields,somb_msg_get_service_resp_size);
}


void somb_daemon_get_sub_ns(somb_msg_get_sub_ns_req *msgsreq,char * ctrl_addr)
{
    bool find_sub_ns = false;
    ST_SOMB_DAEMON_SUB_NS *item=NULL,*destitem=NULL,*tmp=NULL; 
    HASH_ITER(hh, pstDaemonSubNsHead, item, tmp) 
    {
        if(item->id == msgsreq->subns.sub_ns_id)
        {
            find_sub_ns = true;
            break;
        }
    }

    somb_msg_get_sub_ns_resp msgsresp = somb_msg_get_sub_ns_resp_init_zero;
    msgsresp.sub_ns_id = 0;
    msgsresp.pid = getpid();

    if(!find_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon:sub ns(%d) pid(%d) get sub ns(%d) failed.",msgsreq->sub_ns_id,msgsreq->pid,msgsreq->subns.sub_ns_id);
        msgsresp.has_subns = false;
    }
    else
    {
        msgsresp.has_subns = true;
        msgsresp.subns.sub_ns_id =  item->id;
        msgsresp.subns.sub_ns_status =  item->status;
        snprintf(msgsresp.subns.sub_ns_addr,sizeof(msgsresp.subns.sub_ns_addr),"%s",item->addr);
        snprintf(msgsresp.subns.sub_ns_name,sizeof(msgsresp.subns.sub_ns_name),"%s",item->name);
    }

    SOMB_LOG_DEBUG("somb daemon:sub ns(%d) pid(%d) get sub ns(%s)-(%d)-(%s) ok .",msgsreq->sub_ns_id,msgsreq->pid,item->name,item->id,item->addr);
    if(NULL == strstr(ctrl_addr,SOMB_CTRL_FILE))
    {
        HASH_ITER(hh, pstDaemonSubNsHead, destitem, tmp) 
        {
            if(destitem->id == msgsreq->sub_ns_id)
            {
                break;
            }
        }

        if(NULL ==  destitem)
        {
            SOMB_LOG_ERR("somb daemon:sub ns(%d) pid(%d) get sub ns(%d) ok ,return to sub ns(%d) failed.",msgsreq->sub_ns_id,msgsreq->pid,msgsreq->subns.sub_ns_id,msgsreq->sub_ns_id);

            return;
        }

        somb_daemon_msg_send_to_sub_ns(daemon_skfd,destitem,somb_daemon_msgid_get_sub_ns,&msgsresp,
            somb_msg_get_sub_ns_resp_fields,somb_msg_get_sub_ns_resp_size);
    }
    else
    {
        somb_daemon_msg_send_to_ctrl(daemon_ctrl_sk,somb_daemon_msgid_get_sub_ns,&msgsresp,
            somb_msg_get_sub_ns_resp_fields,somb_msg_get_sub_ns_resp_size);
    }

}

void somb_daemon_ctrl_change_service_status(somb_msg_set_service_available *msgreg)
{
    if(NULL == msgreg)
        return;

    ST_SOMB_DAEMON_SUB_NS *reg_self_sub_ns= NULL,*tmp= NULL;
    HASH_ITER(hh, pstDaemonSubNsHead,reg_self_sub_ns, tmp) 
    {
        if(reg_self_sub_ns->id == msgreg->sub_ns_id)
        {
            break;
        }
    }

    if(NULL == reg_self_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon: sub ns(%d)  change service status(%d) failed,because has not reg sub ns before!", 
                     msgreg->sub_ns_id,msgreg->service_available_count);
        return ;
    }


    uint32_t loop = 0;
    for(;loop < msgreg->service_available_count;loop++)
    {
        uint32_t ServiceId = msgreg->service_available[loop].service_id;
        bool available = msgreg->service_available[loop].available;

        ST_SOMB_DAEMON_SERVICE_LIST *s = NULL;
        HASH_FIND_INT(NsServieList,&(ServiceId),s);
        if(NULL != s)
        {
            bool status_changed = true;
            E_SOMB_SERVICEID_STATUS old_staus =s->status;
            if(available && (s->status  != SOMB_SERVICE_STATUS_READY))
            {
                s->status  = SOMB_SERVICE_STATUS_READY;
            }
            else if(!available && (s->status  == SOMB_SERVICE_STATUS_READY))
            {
                s->status  = SOMB_SERVICE_STATUS_INVALID;
            }
            else {
                status_changed =  false;
            }

            if(status_changed)
            {
                SOMB_LOG_WARN("somb daemon: sub ns(%d)  ServiceId(%08x) Status changed(%d->%d)",\
                              msgreg->sub_ns_id ,ServiceId,old_staus, s->status );

                struct somb_daemon_service_listened_subns *item2,*tmp2;
                DL_FOREACH_SAFE(s->listener_sub_ns_list_head,item2,tmp2)
                {
                    if( (s->type == SOMB_SVC_TYPE_METHOD) && 
                        (NULL != item2->listener_info.pstSubNs) &&
                        (item2->listener_info.pstSubNs->status == SOMB_DAEMON_NS_STATUS_ONLINE ) )
                    {
                        somb_daemon_report_servicestatus_to_subns(s,item2->listener_info.pstSubNs, available);
                    }
                }
            }
        }

    }
}

void somb_daemon_ctrl_change_service_status_with_mask(somb_msg_set_service_available_with_mask *msgreg)
{
    if(NULL == msgreg)
        return;

    ST_SOMB_DAEMON_SUB_NS *reg_self_sub_ns= NULL,*tmp= NULL;
    HASH_ITER(hh, pstDaemonSubNsHead,reg_self_sub_ns, tmp) 
    {
        if(reg_self_sub_ns->id == msgreg->sub_ns_id)
        {
            break;
        }
    }

    if(NULL == reg_self_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon: sub ns(%d)  change service status(%d) with mask failed,because has not reg sub ns before!", 
                     msgreg->sub_ns_id,msgreg->available);
        return ;
    }


    ST_SOMB_DAEMON_SERVICE_LIST *s = NULL, *tmp1=NULL;
    HASH_ITER(hh, NsServieList, s, tmp1)
    {
        if( (NULL != s) && \
            ((s->id & msgreg->mask) ==  msgreg->mask_value) )
        {
            bool status_changed = true;
            E_SOMB_SERVICEID_STATUS old_staus =s->status;
            if(msgreg->available && (s->status  != SOMB_SERVICE_STATUS_READY))
            {
                s->status  = SOMB_SERVICE_STATUS_READY;
            }
            else if(!(msgreg->available) && (s->status  == SOMB_SERVICE_STATUS_READY))
            {
                s->status  = SOMB_SERVICE_STATUS_INVALID;
            }
            else {
                status_changed =  false;
            }

            if(status_changed)
            {
                SOMB_LOG_WARN("somb daemon: sub ns(%d)  ServiceId(%08x) Status changed(%d->%d)",\
                              msgreg->sub_ns_id ,s->id, old_staus, s->status );

                struct somb_daemon_service_listened_subns *item2,*tmp2;
                DL_FOREACH_SAFE(s->listener_sub_ns_list_head,item2,tmp2)
                {
                    if( (s->type == SOMB_SVC_TYPE_METHOD) && 
                        (NULL != item2->listener_info.pstSubNs) &&
                        (item2->listener_info.pstSubNs->status == SOMB_DAEMON_NS_STATUS_ONLINE ) )
                    {
                        somb_daemon_report_servicestatus_to_subns(s,item2->listener_info.pstSubNs, msgreg->available);
                    }
                }
            }

        }//s != NULL
    } //hash_iter

}



void somb_daemon_reg_listen_service(somb_event_listener_reg_2_bus *msgreg)
{
    uint32_t loop = 0;
    int32_t ret;

    ST_SOMB_DAEMON_SUB_NS *reg_self_sub_ns= NULL,*tmp= NULL;
    HASH_ITER(hh, pstDaemonSubNsHead,reg_self_sub_ns, tmp) 
    {
        if(reg_self_sub_ns->id == msgreg->subns.sub_ns_id)
        {
            break;
        }
    }

    if(NULL == reg_self_sub_ns)
    {
        SOMB_LOG_ERR("somb daemon: sub ns(%d)  reg event listener eventnum(%d) failed,because has not reg sub ns before!", msgreg->subns.sub_ns_id,msgreg->service_item_count);
        return ;
    }

    for(;loop < msgreg->service_item_count;loop++)
    {
        uint32_t ServiceId = msgreg->service_item[loop].service_id;
        ST_SOMB_DAEMON_SERVICE_LIST *s = NULL;
        HASH_FIND_INT(NsServieList,&(ServiceId),s);
        //bool bServiceAvailable = true;
        if(NULL == s)
        {
            s = (ST_SOMB_DAEMON_SERVICE_LIST*)malloc(sizeof *s);
            bzero(s,sizeof(*s));

            s->id = ServiceId; 
            s->status = SOMB_SERVICE_STATUS_INVALID;
            s->type = SOMB_SVC_TYPE_INVALID; 
            s->pstNsAddr = NULL;
            s->listener_sub_ns_list_head=NULL;
            HASH_ADD_INT(NsServieList, id, s);
            SOMB_LOG_INFO("somb daemon: sub ns(%d) reg event listener new ServiceId(%08x)", msgreg->subns.sub_ns_id,ServiceId);
            //bServiceAvailable = false; //new service when reg listen , the available should be false
        }

        struct somb_daemon_service_listened_subns *item2,*tmp2;
        if(msgreg->reg)
        {
            bool bfind_in_listen_list = false;
            //To check wether the listner already in service's subns listen list
            DL_FOREACH_SAFE(s->listener_sub_ns_list_head,item2,tmp2)
            {
                if(item2->listener_info.pstSubNs->id == reg_self_sub_ns->id)
                {
                    bfind_in_listen_list = true;
                    break;
                }
            }

            //if the check result is ng, add the listener to the list
            if(!bfind_in_listen_list)
            {
                struct somb_daemon_service_listened_subns *listened_subns = malloc(sizeof(struct somb_daemon_service_listened_subns));
                memset(listened_subns,0,sizeof(struct somb_daemon_service_listened_subns));

                listened_subns->listener_info.pstSubNs = reg_self_sub_ns;//s->pstNsAddr;
                listened_subns->listener_info.listener_flags = msgreg->flags[loop];
                DL_PREPEND(s->listener_sub_ns_list_head,listened_subns);
                SOMB_LOG_INFO("somb daemon: add listener subns(%d) for serviceid(%08x) ",msgreg->subns.sub_ns_id,ServiceId);
            }

            //only service type=method's status should be reported to listener
            if((s->status == SOMB_SERVICE_STATUS_READY)&&(s->type == SOMB_SVC_TYPE_METHOD))
            {
                somb_daemon_report_servicestatus_to_subns(s,reg_self_sub_ns,true);
            }
        }
        else // unregister listener
        {
            /*when unlisten to the service id, 
             * if the service is a event type service, the daemon should send delete msg to event provider
             * if the service is a method type service,the daemon should delete the listenerinfo from it's stener_sub_ns_list_head
            */
            if(s->type == SOMB_SVC_TYPE_EVENT)
            {
                // do it later
            }
            else if (s->type == SOMB_SVC_TYPE_METHOD)
            {
                DL_FOREACH_SAFE(s->listener_sub_ns_list_head,item2,tmp2)
                {
                    if((item2->listener_info.pstSubNs == reg_self_sub_ns)&&(s->type == SOMB_SVC_TYPE_METHOD))
                    {
                        // unlisten the method service will not casue the available status changing
                        //somb_daemon_report_servicestatus_to_subns(s,reg_self_sub_ns,false);

                        SOMB_LOG_INFO("somb daemon: del listener subns(%d) for serviceid(%08x) ",msgreg->subns.sub_ns_id,ServiceId);
                        /* then delete the listener info from the listener_sub_ns_list_head */
                        DL_DELETE(s->listener_sub_ns_list_head,item2);
                        break;
                    }
                }

            }

        }

        //if Service Type is Event, should notify the event provider with the listener's info
        if((NULL != s->pstNsAddr)&&(s->type == SOMB_SVC_TYPE_EVENT))
        {
            somb_event_listener_reg_2_subns msg = somb_event_listener_reg_2_subns_init_zero;
            msg.service_id = ServiceId;
            msg.flags_count = 1;
            msg.flags[0]= msgreg->flags[loop];

            msg.subns_count = 1;
            msg.reg = msgreg->reg;
            msg.subns[0].sub_ns_id = reg_self_sub_ns->id;
            snprintf(msg.subns[0].sub_ns_addr,sizeof(msg.subns[0].sub_ns_addr),"%s",reg_self_sub_ns->addr);
            snprintf(msg.subns[0].sub_ns_name,sizeof(msg.subns[0].sub_ns_name),"%s",reg_self_sub_ns->name);
            //notify the sub ns which provide the event 
            ret =somb_daemon_msg_send_to_sub_ns(daemon_skfd,s->pstNsAddr,somb_daemon_msgid_listen_event_2_subns,\
                    &msg, somb_event_listener_reg_2_subns_fields, somb_event_listener_reg_2_subns_size);
            if(SOMB_OK != ret)
            {
                SOMB_LOG_ERR("somb daemon: sub ns(%d)  send listen serviceid(%08x) to subns(%d) fail",msgreg->subns.sub_ns_id,ServiceId,s->pstNsAddr->id);
            }
        }
    }

    SOMB_LOG_INFO("somb daemon: (%s)sub ns(%d)  reg(%d) event listener eventnum(%d) done", 
                  msgreg->subns.sub_ns_name,
                  msgreg->subns.sub_ns_id,
                  msgreg->reg,
                  msgreg->service_item_count);

}


int32_t somb_daemon_config_init()
{
    FILE *file = fopen(SOMB_DAEMON_CONFIG,"w+");
    if(NULL == file)
    {
        printf("somb daemon:open [%s] failed,errno=%s\n",SOMB_DAEMON_CONFIG,strerror(errno));
        return -1;
    }

    if(fwrite(gstSombConf.conf_path,1,sizeof(gstSombConf.conf_path),file) <= 0)
    {
        printf("somb daemon:write [%s] with conf path failed,errno=%s\n",SOMB_DAEMON_CONFIG,strerror(errno));
        return -1;
    }

    fclose(file);

    return 0;
}

void somb_daemon_ctrl_get_sub_ns()
{

}

void somb_daemon_get_reg_subns(char *addr)
{
    somb_reg_sub_ns  RegSubNs = somb_reg_sub_ns_init_zero;

    ST_SOMB_DAEMON_SUB_NS *reg_self_sub_ns= NULL,*tmp= NULL;
    uint32_t loop = 0;
    HASH_ITER(hh, pstDaemonSubNsHead,reg_self_sub_ns, tmp) 
    {
        RegSubNs.reg_ns_list[loop].sub_ns_id = reg_self_sub_ns->id;
        RegSubNs.reg_ns_list[loop].sub_ns_pid = reg_self_sub_ns->pid;
        RegSubNs.reg_ns_list[loop].sub_ns_status = reg_self_sub_ns->status;
        sprintf(RegSubNs.reg_ns_list[loop].sub_ns_name,"%s",reg_self_sub_ns->name);

        struct somb_daemon_subns_owned_service *item1=NULL,*tmp1=NULL;
        uint32_t i = 0;
        DL_FOREACH_SAFE(reg_self_sub_ns->owned_servicelist_head,item1,tmp1)
        {
            //SOMB_LOG_DEBUG("somb daemon: SubNs(%s)(%d) owned service(%08x) type(%d)",reg_self_sub_ns->name,reg_self_sub_ns->pid,item1->pstService->id,item1->pstService->type);

            RegSubNs.reg_ns_list[loop].service_info[i].service_id = item1->pstService->id;
            RegSubNs.reg_ns_list[loop].service_info[i].service_type = item1->pstService->type;
            RegSubNs.reg_ns_list[loop].service_info[i].service_status = item1->pstService->status;
            i++;

            if(i >= 128)
            {
                SOMB_LOG_WARN("somb daemon: SubNs(%s)(%d) owned service num beyond 128",reg_self_sub_ns->name,reg_self_sub_ns->pid);
                break;
            }
        }
        RegSubNs.reg_ns_list[loop].service_info_count = i;
        SOMB_LOG_DEBUG("somb daemon: SubNs(%s)(%d) owned service num(%d)",reg_self_sub_ns->name,reg_self_sub_ns->pid,i);

        loop++;
    }

    //RegSubNs.reg_ns_list_count =  HASH_COUNT(pstDaemonSubNsHead);
    RegSubNs.reg_ns_list_count =  loop;

    int ret =somb_daemon_msg_send_to_ctrl(daemon_ctrl_sk,somb_daemon_msgid_get_reg_sub_ns_list,\
            &RegSubNs, somb_reg_sub_ns_fields, somb_reg_sub_ns_size);
    if(SOMB_OK != ret)
    {
        SOMB_LOG_ERR("somb daemon:  send to ctrl reg sub ns list fail");
    }
}

void somb_daemon_client_msg_process(uint8_t *tmpbuffer,uint32_t recvlen,char *SrcAddr)
{

    bool status = false;
    uint32_t MsgId,MsgLen=0,processed_msg_len=0;
    uint8_t *buffer = tmpbuffer;

    do
    {
        MsgId = *(uint32_t*)buffer;
        MsgLen = *(uint32_t*)(buffer+4);


        pb_istream_t stream = pb_istream_from_buffer(&(buffer[SOMB_DAEMON_MSG_HEADER_SIZE]), MsgLen);
        SOMB_LOG_DEBUG("somb daemon: len(%d) recv MsgId=%d  MsgLen=%d",recvlen,MsgId,MsgLen);

        switch(MsgId)
        {
            case somb_daemon_msgid_register_sub_ns:
                {
                    somb_sub_ns_reg_req msgreq = somb_sub_ns_reg_req_init_zero;
                    status = pb_decode(&stream, somb_sub_ns_reg_req_fields, &msgreq);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: sub ns register,but decode msg failed,%s",PB_GET_ERROR(&stream));
                        break;
                    }
                    somb_daemon_reg_subns(&msgreq);
                }
                break;
            case somb_daemon_msgid_register:
                {
                    somb_msg_reg msgreg = somb_msg_reg_init_zero;
                    status = pb_decode(&stream, somb_msg_reg_fields, &msgreg);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: register service, decode msg failed");
                        break;
                    }

                    somb_daemon_reg_service(&msgreg);
                }
                break;
            case somb_daemon_msgid_unregister:
                {
                    somb_msg_unreg msgunreg = somb_msg_unreg_init_zero;
                    status = pb_decode(&stream, somb_msg_unreg_fields, &msgunreg);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: unregister decode msg failed");
                        break;
                    }

                    somb_daemon_unreg_service(&msgunreg);
                }
                break;
            case somb_daemon_msgid_get_service:
                {
                    somb_msg_get_service_req msgsreq= somb_msg_get_service_req_init_zero;
                    status = pb_decode(&stream, somb_msg_get_service_req_fields, &msgsreq);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: get service decode msg failed");
                        break;
                    }

                    somb_daemon_get_service(&msgsreq);
                }
                break;
            case somb_daemon_msgid_get_sub_ns:
                {
                    somb_msg_get_sub_ns_req msgsreq= somb_msg_get_sub_ns_req_init_zero;
                    status = pb_decode(&stream, somb_msg_get_sub_ns_req_fields, &msgsreq);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: get service decode msg failed");
                        break;
                    }

                    somb_daemon_get_sub_ns(&msgsreq,SrcAddr);
                }
                break;
            case somb_daemon_msgid_listen_event_2_bus:
                {
                    somb_event_listener_reg_2_bus msgsreq= somb_event_listener_reg_2_bus_init_zero;
                    status = pb_decode(&stream, somb_event_listener_reg_2_bus_fields, &msgsreq);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: reg listen event  decode msg failed");
                        break;
                    }

                    somb_daemon_reg_listen_service(&msgsreq);
                }
                break;
            case somb_daemon_msgid_get_reg_sub_ns_list:
                somb_daemon_get_reg_subns(SrcAddr);
                break;
            case somb_daemon_msgid_ctrl_get_sub_ns_status:
                somb_daemon_ctrl_get_sub_ns();
                break;
            case somb_daemon_msgid_service_change_available:
                {
                    somb_msg_set_service_available msgsreq= somb_msg_set_service_available_init_zero;
                    status = pb_decode(&stream, somb_msg_set_service_available_fields, &msgsreq);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: change service status decode msg failed");
                        break;
                    }
                    somb_daemon_ctrl_change_service_status(&msgsreq);
                }
                break;
            case somb_daemon_msgid_service_change_available_with_mask:
                {
                    somb_msg_set_service_available_with_mask msgsreq= somb_msg_set_service_available_with_mask_init_zero;
                    status = pb_decode(&stream, somb_msg_set_service_available_with_mask_fields, &msgsreq);
                    if (!status)
                    {
                        SOMB_LOG_ERR("somb daemon: change service status with mask decode msg failed");
                        break;
                    }
                    somb_daemon_ctrl_change_service_status_with_mask(&msgsreq);
                }
                break;
            default:
                SOMB_LOG_ERR("somb daemon: get unsupported msgid(%d) failed",MsgId);
                break;
        }

        processed_msg_len += SOMB_DAEMON_MSG_HEADER_SIZE + MsgLen;

        buffer = tmpbuffer + processed_msg_len;
    }while(processed_msg_len < recvlen);
}
static void print_backstrace()
{
    //how to know current gcc support backstrace or not
#if 0
    void *buffer[30] = {0};
    size_t size;
    char **strings;
    size_t i;
    size = backtrace(buffer, 30);
    strings = backtrace_symbols(buffer, size);
    if (NULL != strings)
    {

        for (i = 0; i < size; i++)
        {
            SOMB_LOG_ERR("%uz:%s", i, strings[i]);
        }

        free(strings);
        strings = NULL;
    }
#endif
}
static void somb_daemon_sigv_handle(int32_t sig)
{
    SOMB_LOG_ERR("exit !!!!!!!!!! sig=%d", sig);
    print_backstrace();
    exit(1);
    return;
}

int main(int argc,char *argv[])
{
    signal(SIGSEGV, somb_daemon_sigv_handle);
    signal(SIGBUS, somb_daemon_sigv_handle);
    signal(SIGTRAP, somb_daemon_sigv_handle);
    signal(SIGTERM, somb_daemon_sigv_handle);

    int32_t ret;
    if(argc == 1)
    {
        printf("somb daemon: somb.yaml is not specifed\n");
        return -1;
    }

    if(access(argv[1],F_OK) != 0)
    {
        printf("somb daemon: the config file of somb[%s] doesn't not exist\n",argv[1]);
        return -1;
    }

    if(0 != somb_config_file_parser(argv[1],&gstSombConf))
    {
        printf("somb daemon: the config file of somb[%s] has some wrong configurations\n",argv[1]);
        return -1;
    }

    mkdir(SOMB_DAEMON_PATH,0666);
    
    if(0 != somb_daemon_config_init())
    {
        return -1;
    }

    st_somb_logfile_config stlogfileconf;
    sprintf(stlogfileconf.log_path,"%s",gstSombConf.log_path);
    stlogfileconf.log_level = gstSombConf.log_level;
    stlogfileconf.log_file_size = gstSombConf.log_file_size;
    stlogfileconf.log_file_num = gstSombConf.log_file_num;

    if( 0 != somb_log_init(&stlogfileconf))
    {
        return -1;
    }
    daemon_skfd = socket(AF_UNIX,SOCK_STREAM|SOCK_CLOEXEC,0);
    if(-1 == daemon_skfd)
    {
        printf("somb daemon creat socket error.%s\n",strerror(errno));
        return -1;
    }
    struct sockaddr_un daemon_addr_un;
    memset(&daemon_addr_un,0,sizeof(struct sockaddr_un));

    daemon_addr_un.sun_family = AF_UNIX;
    snprintf(daemon_addr_un.sun_path,sizeof(daemon_addr_un.sun_path),SOMB_DAEMON_ADDR);
    unlink(SOMB_DAEMON_ADDR);
    if(bind(daemon_skfd,( struct sockaddr *)&daemon_addr_un,SUN_LEN(&daemon_addr_un)) < 0)
    {
        SOMB_LOG_ERR("somb daemon bind addr(%s) error.%s",SOMB_DAEMON_ADDR,strerror(errno));
        return SOMB_FAIL;
    }

    if(listen(daemon_skfd,5) < 0)
    {
        SOMB_LOG_ERR("somb daemon listen return failed,addr(%s) error.%s",SOMB_DAEMON_ADDR,strerror(errno));
        return SOMB_FAIL;
    }
    
    ret = somb_daemon_msg_init();
    if(SOMB_OK != ret)
    {
        SOMB_LOG_ERR("somb daemon msg init failed ");
        return SOMB_FAIL;
    }

    int epfd = epoll_create(5);
    if(epfd == -1)
    {
        SOMB_LOG_ERR("somb daemon epoll create return failed, error.%s",strerror(errno));
        return SOMB_FAIL;
    }
    struct epoll_event ep_event={0};
    ep_event.data.fd = daemon_skfd;
    ep_event.events = EPOLLIN;

    if(epoll_ctl(epfd,EPOLL_CTL_ADD,daemon_skfd,&ep_event) == -1)
    {
        SOMB_LOG_ERR("somb daemon epoll ctl(ADD) daemon_skfd return failed, error.%s",strerror(errno));
        return SOMB_FAIL;
    }
    
    SOMB_LOG_INFO("somb daemon Ver:%s start to run",SOMB_VERSION);
    while(1){
        struct epoll_event pEvent[10];
        memset(pEvent,0,sizeof(struct epoll_event)*10);

        int eventnum = epoll_wait(epfd,pEvent,10,-1);
        if( eventnum <= 0)
        {
            SOMB_LOG_ERR("somb daemon epoll wait return failed(%d), error.%s",eventnum,strerror(errno));
            continue;
        }
        SOMB_LOG_DEBUG("somb daemon:epoll wait return %d",eventnum);

        int clientfd;
        struct sockaddr_un client_addr_un = {0};
        socklen_t socklen = sizeof(client_addr_un.sun_path);
        uint8_t loop = 0;
        for(loop=0;loop<eventnum;loop++)
        {
            if((pEvent[loop].data.fd == daemon_skfd)&&(pEvent[loop].events & EPOLLIN))
            {
                SOMB_LOG_DEBUG("somb daemon:prepare to accept new client");
                clientfd = accept4(pEvent[loop].data.fd,(struct sockaddr*)&client_addr_un,(socklen_t *)&socklen,SOCK_CLOEXEC);
                if(clientfd == -1)
                {
                    SOMB_LOG_ERR("somb daemon accept4 new client failed(%d), error.%s",clientfd,strerror(errno));
                }
                else
                {
                    //add new epoll item
                    memset(&ep_event,0,sizeof(struct epoll_event));
                    ep_event.data.fd = clientfd;
                    ep_event.events = EPOLLIN|EPOLLRDHUP;
                    epoll_ctl(epfd,EPOLL_CTL_ADD,clientfd,&ep_event);

                    if(strstr(client_addr_un.sun_path,"somb_ctrl") == NULL)
                    {
                        uint32_t client_pid=0;
                        uint8_t client_name[32]={0};
                        memset(client_name,0,sizeof(client_name));
                        sscanf(client_addr_un.sun_path,SOMB_SUB_NS_ADDR_FMT0,&client_pid,client_name);
                        strtok(client_name,"-");

                        SOMB_LOG_INFO("somb daemon add client(%s) pid(%d) addr(%s) fd(%d)  ",client_name,client_pid,client_addr_un.sun_path,clientfd);
                        somb_daemon_add_subns(client_name,client_pid,clientfd);
                    }
                    else
                    {
                        SOMB_LOG_INFO("somb daemon ctrl is connected fd(%d)",clientfd);
                        daemon_ctrl_sk = clientfd;
                    }

                }
            }
            else
            {

                if(pEvent[loop].events & EPOLLRDHUP)
                {
                    close(pEvent[loop].data.fd);
                    epoll_ctl(epfd, EPOLL_CTL_DEL, pEvent[loop].data.fd, NULL);
                    if(pEvent[loop].data.fd == daemon_ctrl_sk)
                    {
                        SOMB_LOG_WARN("somb daemon delete ctrl fd(%d)  ",pEvent[loop].data.fd);
                    }
                    else
                    {
                        SOMB_LOG_WARN("somb daemon delete client fd(%d)  ",pEvent[loop].data.fd);
                        somb_daemon_remove_subns_by_fd(pEvent[loop].data.fd);
                    }
                }
                else if(pEvent[loop].events & EPOLLIN)
                {
                    SOMB_LOG_DEBUG("somb daemon:prepare to recv message from client fd(%d)",pEvent[loop].data.fd);
                    uint8_t buffer[SOMB_DAEMON_MSG_HEADER_SIZE+4096*4];
                    struct sockaddr_un addr_un;
                    socklen_t socklen=sizeof(struct sockaddr_un);
                    memset(&addr_un,0,sizeof(struct sockaddr_un));
                    int32_t len = recvfrom(pEvent[loop].data.fd,buffer,sizeof(buffer),0,(struct sockaddr *)&addr_un,&socklen);
                    if(len == -1)
                    {
                        SOMB_LOG_WARN("somb daemon recv len error(%s) ",strerror(errno));
                    }
                    else if(len == 0)
                    {
                        close(pEvent[loop].data.fd);
                        epoll_ctl(epfd, EPOLL_CTL_DEL, pEvent[loop].data.fd, NULL);
                        SOMB_LOG_WARN("somb daemon delete client fd(%d) (%s) ",pEvent[loop].data.fd,addr_un.sun_path);
                        somb_daemon_remove_subns_by_fd(pEvent[loop].data.fd);
                    }
                    else
                    {
                        somb_daemon_client_msg_process(buffer,len,addr_un.sun_path);
                    }
                }

            }
        }//for
    }//while
}
